#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
#include "shmem.h"
#include "MQTTClient.h"
#include <pthread.h>
#include "msg_queue_peer.h"

#define ADDRESS "tcp://192.168.0.160:1883"
#define CLIENTID "linuxGateway"
// 指令控制  Qt->Linux
#define COMMAND_CONTROL_TOPIC "DataSubmitProcess/CommandControl"
// 设备状态上报 Linux->QT
#define DEVICES_STATA_TOPIC "DataSubmitProcess/DevicesStata"

#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
#define isOpenDebug 1
// 控制多长时间发送一次
#define UPDADA_DURATION 3

static struct shm_param para;

typedef struct
{
    int key;
    char name[32];
    int type;
    int typeStata;
    int value;
    float floatValue;
} Stm32Data;

typedef struct
{
    int key;
    char name[32];
    int addr;
    int type;
    int typeStata;
    int value;
} ModbusData;

typedef struct
{
    int key;
    char name[32];
    int type;
    int typeStata;
    int addr;
    int value;
} MetaServerData;

typedef struct
{
    Stm32Data stm32_list[8];   // 固定数组，存储stm32数据
    int stm32_count;           // 实际有效数量
    ModbusData modbus_list[6]; // 固定数组，存储modbus数据
    int modbus_count;
    MetaServerData meta_list[7]; // 固定数组，存储metaServer数据
    int meta_count;
} DeviceData;

// 消息队列结构体
struct msgbuf
{
    long mtype;
    char mdata[256];
};

char const *mqttIPAndPort = "";  

/**
 * @brief 打印错误信息
 *
 */
void printError(int lineNumber)
{
#if isOpenDebug
    printf("----------------------%d\n", lineNumber);
#endif
}

volatile MQTTClient_deliveryToken deliveredtoken;



static struct shm_param para;

DeviceData *shm_device = NULL;


void delivered(void *context, MQTTClient_deliveryToken dt)
{
    printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

/**
 * @brief 消息接收回调函数
 *
 */
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int i;
    char *payloadptr;

    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: ");

    payloadptr = message->payload;
    for (i = 0; i < message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');

    cJSON *root = cJSON_Parse((char *)message->payload);

    if (root == NULL)
    {
        printf("parse json failed\n");
        return -1;
    }

    struct msgbuf send_buf;
    // 这个mtype可以不用，但是必须赋一个不小于0的数
    send_buf.mtype = 1;
    // 直接将消息内容复制到mdata
   // strcpy(send_buf.mdata, (char *)message->payload);
   char *json = cJSON_PrintUnformatted(root);
   strncpy(send_buf.mdata, json, sizeof(send_buf.mdata) - 1);
    printf("send_buf.mdata is : %s\n", send_buf.mdata);
   

    if (cJSON_HasObjectItem(root, "stm32"))
    {
        if (msg_queue_send("stm32", (char *)&send_buf, sizeof(send_buf), 0) < 0)

        {
            printf("msg_queue_send error\n");
            return -1;
        }

        printf("stm32 msg_queue_send success\n");
    }

    if (cJSON_HasObjectItem(root, "modbus"))
    {
        if (msg_queue_send("modbus", (char *)&send_buf, sizeof(send_buf), 0) < 0)
        {
            printf("msg_queue_send error\n");
            return -1;
        }
        printf("modbus msg_queue_send success\n");
    }

    if (cJSON_HasObjectItem(root, "metaServer"))
    {
        if (msg_queue_send("metaServer", (char *)&send_buf, sizeof(send_buf), 0) < 0)
        {
            printf("msg_queue_send error\n");
            return -1;
        }
        printf("metaServer msg_queue_send success\n");
    }

    // 释放内存
    cJSON_Delete(root);

    MQTTClient_freeMessage(&message);
    // MQTTClient_free(topicName);

    return 1;
}

/**
 * @brief 连接丢失回调函数
 *
 */
void connlost(void *context, char *cause)
{
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}

/**
 * @brief 解析stm32数据
 *
 */
static int parse_stm32(cJSON *stm32_obj, DeviceData *device)
{
    cJSON *data_array = cJSON_GetObjectItem(stm32_obj, "data");

    device->stm32_count = cJSON_GetArraySize(data_array);

    printError(__LINE__);
    printf("----%d\n", device->stm32_count);

    // 遍历数组，直接填充固定数组（无需malloc）
    for (int i = 0; i < device->stm32_count; i++)
    {
        cJSON *item = cJSON_GetArrayItem(data_array, i);
        Stm32Data *stm = &device->stm32_list[i]; // 访问固定数组元素

        // 解析字段（逻辑不变）
        cJSON *key = cJSON_GetObjectItem(item, "key");
        stm->key = key ? key->valueint : -1;

        cJSON *name = cJSON_GetObjectItem(item, "name");
        strncpy(stm->name, name->valuestring, sizeof(stm->name) - 1);

        // 其他字段（type、typeStata、value、floatValue）解析同理...
        cJSON *type = cJSON_GetObjectItem(item, "type");
        stm->type = type ? type->valueint : -1;

        cJSON *typeStata = cJSON_GetObjectItem(item, "typeStata");
        stm->typeStata = typeStata ? typeStata->valueint : -1;

        cJSON *value = cJSON_GetObjectItem(item, "value");
        stm->value = value ? value->valueint : 0;

        cJSON *floatValue = cJSON_GetObjectItem(item, "floatValue");
        stm->floatValue = floatValue ? (float)floatValue->valuedouble : 0.0f;
    }
    printError(__LINE__);

    return 0;
}

/**
 * @brief 解析modbus数据
 *
 */
static int parse_modbus(cJSON *modbus_obj, DeviceData *device)
{

    cJSON *data_array = cJSON_GetObjectItem(modbus_obj, "data");

    device->modbus_count = cJSON_GetArraySize(data_array);

    if (!device->modbus_list)
    {
        printf("malloc modbus_list failed\n");
        return -1;
    }

    for (int i = 0; i < device->modbus_count; i++)
    {

        cJSON *item = cJSON_GetArrayItem(data_array, i);
        ModbusData *modbus = &device->modbus_list[i];

        cJSON *key = cJSON_GetObjectItem(item, "key");
        modbus->key = key->valueint;

        cJSON *name = cJSON_GetObjectItem(item, "name");
        strncpy(modbus->name, name->valuestring, sizeof(modbus->name) - 1);

        cJSON *addr = cJSON_GetObjectItem(item, "addr");
        modbus->addr = addr->valueint;

        cJSON *type = cJSON_GetObjectItem(item, "type");
        modbus->type = type->valueint;

        cJSON *typeStata = cJSON_GetObjectItem(item, "typeStata");

        modbus->typeStata = typeStata->valueint;
        cJSON *value = cJSON_GetObjectItem(item, "value");

        modbus->value = value->valueint;
    }
    return 0;
}

/**
 * @brief 解析元宇宙数据
 *
 */

static int parse_metaserver(cJSON *meta_obj, DeviceData *device)
{
    cJSON *data_array = cJSON_GetObjectItem(meta_obj, "data");

    device->meta_count = cJSON_GetArraySize(data_array);

    if (!device->meta_list)
    {
        printf("malloc meta_list failed\n");
        return -1;
    }

    for (int i = 0; i < device->meta_count; i++)
    {
        cJSON *item = cJSON_GetArrayItem(data_array, i);
        MetaServerData *meta = &device->meta_list[i];

        // 必选字段解析（参考stm32的解析逻辑）
        cJSON *key = cJSON_GetObjectItem(item, "key");
        meta->key = key->valueint;

        cJSON *name = cJSON_GetObjectItem(item, "name");
        strncpy(meta->name, name->valuestring, sizeof(meta->name) - 1);

        cJSON *type = cJSON_GetObjectItem(item, "type");
        meta->type = type->valueint;

        cJSON *typeStata = cJSON_GetObjectItem(item, "typeStata");
        meta->typeStata = typeStata->valueint;

        cJSON *addr = cJSON_GetObjectItem(item, "addr");
        meta->addr = addr->valueint;
    }
    return 0;
}

/**
 * @brief 解析json数据并映射到内存

 *
*/
DeviceData *device_data_init(const char *json_str)
{

    printError(__LINE__);
 DeviceData *device = (DeviceData *)calloc(1, sizeof(DeviceData)); // 初始化为0
    if (!device)
        return NULL;

    cJSON *root = cJSON_Parse(json_str);
    if (!root)
    {
        printf("parse json failed: %s\n", cJSON_GetErrorPtr());
        free(device);
        return NULL;
    }

    // 分别解析三大块数据
    cJSON *stm32_obj = cJSON_GetObjectItem(root, "stm32");

    if (stm32_obj && parse_stm32(stm32_obj, device) != 0)
    {
        goto error;
    }

    cJSON *modbus_obj = cJSON_GetObjectItem(root, "modbus");

    if (modbus_obj && parse_modbus(modbus_obj, device) != 0)
    {
        goto error;
    }

    cJSON *meta_obj = cJSON_GetObjectItem(root, "metaServer");

    if (meta_obj && parse_metaserver(meta_obj, device) != 0)
    {
        goto error;
    }

    cJSON_Delete(root);
    return device;

error:
    // 解析失败时释放已分配的内存
    free(device->stm32_list);
    free(device->modbus_list);
    free(device->meta_list);
    free(device);
    cJSON_Delete(root);
    return NULL;
}

// 释放设备数据内存
void device_data_free(DeviceData *device)
{
    if (device)
    {
        free(device->stm32_list);
        free(device->modbus_list);
        free(device->meta_list);
        free(device);
    }
}

/**
 * @brief 打开配置文件
 *
 */
char *openConfigFile(char const *jsonPath)
{
    // 1. 读取JSON文件（参考之前的文件读取逻辑）
    FILE *fp = fopen(jsonPath, "r");
    if (!fp)
    {
        printf("open file failed\n");
        return NULL;
    }

    fseek(fp, 0, SEEK_END);
    long file_size = ftell(fp);
    rewind(fp);
    char *buf = (char *)malloc(file_size + 1);
    fread(buf, 1, file_size, fp);
    buf[file_size] = '\0';
    fclose(fp);

    return buf;
}

/**
 * @brief 启动mqtt客户端
 *
 */
int startCommitByMQTT()
{
    printError(__LINE__);
    MQTTClient client;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    int rc;
    int ch;
    MQTTClient_deliveryToken token;
    MQTTClient_message pubmsg = MQTTClient_message_initializer;

    MQTTClient_create(&client, mqttIPAndPort, CLIENTID,
                      MQTTCLIENT_PERSISTENCE_NONE, NULL);
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    printError(__LINE__);

    MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);

      printError(__LINE__);

    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
      printError(__LINE__);
    printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n",
           COMMAND_CONTROL_TOPIC, CLIENTID, QOS);

             printError(__LINE__);

    MQTTClient_subscribe(client, COMMAND_CONTROL_TOPIC, QOS);

    printError(__LINE__);

    while (1)
    {
        // 控制多长时间发送一次
        sleep(UPDADA_DURATION);

        cJSON *root = cJSON_CreateObject();
        Stm32Data *stm32 = shm_device->stm32_list;
        // stm32 json
        cJSON *stm32Arry = cJSON_CreateArray();
        for (size_t i = 0; i < shm_device->stm32_count; i++)
        {

            cJSON *obj = cJSON_CreateObject();

            cJSON *keyValue = cJSON_CreateNumber(shm_device->stm32_list[i].key);
            cJSON_AddItemToObject(obj, "key", keyValue);

            cJSON *nameValue = cJSON_CreateString(shm_device->stm32_list[i].name);
            cJSON_AddItemToObject(obj, "name", nameValue);

            cJSON *typeValue = cJSON_CreateNumber(shm_device->stm32_list[i].type);
            cJSON_AddItemToObject(obj, "type", typeValue);

            cJSON *typeStataValue = cJSON_CreateNumber(shm_device->stm32_list[i].typeStata);
            cJSON_AddItemToObject(obj, "typeStata", typeStataValue);

            cJSON *valueValue = cJSON_CreateNumber(shm_device->stm32_list[i].value);
            cJSON_AddItemToObject(obj, "value", valueValue);

            cJSON *floatValueValue = cJSON_CreateNumber(shm_device->stm32_list[i].floatValue);
            cJSON_AddItemToObject(obj, "floatValue", floatValueValue);

            cJSON_AddItemToArray(stm32Arry, obj);
        }
        cJSON *data_obj = cJSON_CreateObject();
        cJSON_AddItemToObject(data_obj, "data", stm32Arry);
        cJSON *stm32Obj = cJSON_CreateObject();
        cJSON_AddItemToObject(root, "stm32", data_obj);

        // modbus json
        cJSON *modbusArry = cJSON_CreateArray();
        for (size_t i = 0; i < shm_device->modbus_count; i++)

        {

            cJSON *obj = cJSON_CreateObject();

            cJSON *keyValue = cJSON_CreateNumber(shm_device->modbus_list[i].key);
            cJSON_AddItemToObject(obj, "key", keyValue);

            cJSON *nameValue = cJSON_CreateString(shm_device->modbus_list[i].name);
            cJSON_AddItemToObject(obj, "name", nameValue);

            cJSON *typeValue = cJSON_CreateNumber(shm_device->modbus_list[i].type);
            cJSON_AddItemToObject(obj, "type", typeValue);

            cJSON *typeStataValue = cJSON_CreateNumber(shm_device->modbus_list[i].typeStata);
            cJSON_AddItemToObject(obj, "typeStata", typeStataValue);

            cJSON *valueValue = cJSON_CreateNumber(shm_device->modbus_list[i].value);
            cJSON_AddItemToObject(obj, "value", valueValue);

            cJSON *addrValue = cJSON_CreateNumber(shm_device->modbus_list[i].addr);
            cJSON_AddItemToObject(obj, "addr", addrValue);

            cJSON_AddItemToArray(modbusArry, obj);
        }

        cJSON *modbusData = cJSON_CreateObject();
        cJSON_AddItemToObject(modbusData, "data", modbusArry);
        cJSON *modbusObj = cJSON_CreateObject();
        cJSON_AddItemToObject(root, "modbus", modbusData);

        cJSON *metaArry = cJSON_CreateArray();
        for (size_t i = 0; i < shm_device->meta_count; i++)

        {

            cJSON *obj = cJSON_CreateObject();

            cJSON *keyValue = cJSON_CreateNumber(shm_device->meta_list[i].key);

            cJSON_AddItemToObject(obj, "key", keyValue);

            cJSON *nameValue = cJSON_CreateString(shm_device->meta_list[i].name);

            cJSON_AddItemToObject(obj, "name", nameValue);

            cJSON *typeValue = cJSON_CreateNumber(shm_device->meta_list[i].type);

            cJSON_AddItemToObject(obj, "type", typeValue);

            cJSON *typeStataValue = cJSON_CreateNumber(shm_device->meta_list[i].typeStata);

            cJSON_AddItemToObject(obj, "typeStata", typeStataValue);

            cJSON *valueValue = cJSON_CreateNumber(shm_device->meta_list[i].value);
            cJSON_AddItemToObject(obj, "value", valueValue);

            cJSON *addrValue = cJSON_CreateNumber(shm_device->meta_list[i].addr);
            cJSON_AddItemToObject(obj, "addr", addrValue);

            cJSON_AddItemToArray(metaArry, obj);
        }

        cJSON *metaData = cJSON_CreateObject();
        cJSON_AddItemToObject(metaData, "data", metaArry);
        cJSON *metaObj = cJSON_CreateObject();
        cJSON_AddItemToObject(root, "metaServer", metaData);

        char *json = cJSON_PrintUnformatted(root);
        printf("%s\n", json);

        pubmsg.payload = json;
        pubmsg.payloadlen = strlen(json);
        pubmsg.qos = QOS;
        pubmsg.retained = 0;
        MQTTClient_publishMessage(client, DEVICES_STATA_TOPIC, &pubmsg, &token);
        printf("-------------------send MQTT message finish-------------------\n");

        cJSON_Delete(root);
        free(json);
    }

    // MQTTClient_unsubscribe(client, COMMAND_CONTROL_TOPIC);
    // MQTTClient_disconnect(client, 10000);
    // MQTTClient_destroy(&client);
}
 

int main(int argc, char const *argv[])
{

    if (argc != 2)
    {
        printf("Use ./ecxe  <tcp://ip:port>   to start server,default port:1883 \n");


        return -1;
    }

    mqttIPAndPort = argv[1];


    // 1. 读取点表配置文件
    char *buf = openConfigFile("config.json");

    // 2. 解析JSON映射内存结构体
    DeviceData *device = device_data_init(buf);

    free(buf);

    //  创建共享内存
    int ret = shm_init(&para, "main.c", sizeof(DeviceData));
    if (ret < 0)
    {
        perror("shm_init failed");
        device_data_free(device);
        return -1;
    }

    //  获取共享内存地址
    shm_device = (DeviceData *)shm_getaddr(&para);
    if (!shm_device)
    {
        perror("shm_getaddr failed");
        device_data_free(device);
        return -1;
    }

    // 将本地device数据复制到共享内存
    memcpy(shm_device, device, sizeof(DeviceData));
    printf("数据已写入共享内存\n");

    // 验证共享内存数据（可选）
    printf("共享内存中stm32第一个数据名称：%s\n", shm_device->stm32_list[0].name);

    printf("共享内存中modbus第一个数据名称：%d\n", shm_device->modbus_list[0].value);

    printf("共享内存中metaServer第一个数据名称：%d\n", shm_device->meta_list[0].key);

    pthread_t mqtt_thread;

    if (pthread_create(&mqtt_thread, NULL, (void *)startCommitByMQTT, NULL) != 0)
    {
        perror("startCommitByMQTT error");
    };

    pthread_join(mqtt_thread, NULL);

    // 4. 释放内存
    // device_data_free(device);
    return 0;
}
